/*************************************************************************/
/*									 */
/*	Main routine, c4.5						 */
/*	------------------						 */
/*									 */
/*************************************************************************/


#include "defns.i"
#include "types.i"
#include <stdlib.h>
#include <malloc.h>
#include <vector>

#include "getdata.h"
#include "trees.h"
#include "st-thresh.h"
#include "getopt.h"
#include "getnames.h"
#include "besttree.h"
#include "header.h"

/*  External data, described in extern.i  */
vector<CString> vecstrOutput;

short		MaxAtt, MaxClass, MaxDiscrVal = 2;

ItemNo		MaxItem;

Description	*Item;

DiscrValue	*MaxAttVal;

char		*SpecialStatus;

String		*ClassName,
	*AttName,
	**AttValName,
	FileName = "DF";

short		VERBOSITY = 0,
	TRIALS    = 10;

Boolean		GAINRATIO  = true,
	SUBSET     = false,
	BATCH      = true,
	UNSEENS    = false,
	PROBTHRESH = false;

ItemNo		MINOBJS   = 2,
	WINDOW    = 0,
	INCREMENT = 0;

float		CF = 0.25;

Tree		*Pruned;

Boolean		AllKnown = true;

CString strTemp0, strTemp1, strTemp2, strTemp3;
CString err;
vector<CString> C45(CString strName, unsigned int trial_num, unsigned int window_num, bool unseen)
{
	strName=strName.Left(strName.GetLength()-6);
	wchar_t* wc;
	wc = strName.GetBuffer(strName.GetLength());
	strName.ReleaseBuffer(strName.GetLength());

	int name_num;
	name_num=WideCharToMultiByte(CP_ACP,0,wc,-1,NULL,0,NULL,NULL);

	char* filename;
	filename = new char[name_num];
	WideCharToMultiByte(CP_ACP,0,wc,-1,filename,name_num,0,0);
	int o;
	extern char *optarg;
	extern int optind;
	Boolean FirstTime=true;
	short Best, BestTree();

	PrintHeader("decision tree generator");


	if ( FirstTime )
	{
		vecstrOutput.push_back(_T("\n    Options:\n"));
		FirstTime = false;
	}

	FileName = filename;
	strTemp0 = filename;

	vecstrOutput.push_back(_T("\tFile stem<")+strTemp0+_T("> \n"));
	//AfxMessageBox(_T("\tFile stem <")+strTemp+_T("> \n"));
	if(trial_num)
	{
		TRIALS=trial_num;
		strTemp0.Format(_T("%d"),TRIALS);
		vecstrOutput.push_back(_T("\tWindowing enabled with") +strTemp0+ _T("trials\n"));
		Check(TRIALS, 1, 10000);
		BATCH = false;
	}

	if(window_num)
	{
		WINDOW=window_num;
		strTemp0.Format(_T("%d"),WINDOW);
		vecstrOutput.push_back(_T("\tInitial window size of") + strTemp0+ _T("items\n"));
		Check(WINDOW, 1, 1000000);
		BATCH = false;
	}

	if(unseen)
	{
		UNSEENS=true;
		vecstrOutput.push_back(_T("\tTrees evaluated on unseen cases\n"));
	}


	/*  Initialise  */

	GetNames();
	GetData(".data");
	strTemp0.Format(_T("%d"),MaxItem+1);
	strTemp1.Format(_T("%d"),MaxAtt+1);
	strTemp2=FileName;
	vecstrOutput.push_back(_T("\nRead ")+strTemp0+_T(" cases (")+ strTemp1 +_T("attributes) from") + strTemp2+_T(".data\n"));

	/*  Build decision trees  */
	if ( BATCH )
	{
		TRIALS = 1;
		OneTree();
		Best=0;
	}
	else
	{
		Best = BestTree();
	}

	/*  Soften thresholds in best tree  */

	if ( PROBTHRESH )
	{
		vecstrOutput.push_back(_T("Softening thresholds"));
		strTemp0.Format(_T("%d"), Best);
		if ( ! BATCH ) vecstrOutput.push_back(_T(" for best tree from trial ") + strTemp0);
		vecstrOutput.push_back(_T("\n"));
		SoftenThresh(Pruned[Best]);
		vecstrOutput.push_back(_T("\n"));
		PrintTree(Pruned[Best]);
	}

	/*  Save best tree  */

	if ( BATCH || TRIALS == 1 )
	{
		vecstrOutput.push_back(_T("\nTree saved\n"));
	}
	else
	{
		strTemp0.Format(_T("%d"),Best);
		vecstrOutput.push_back(_T("\nBest tree from trial")+strTemp0+ _T(" saved\n"));
		// 		SaveTree(Pruned[Best], ".tree");
	}
	SaveTree(Pruned[Best], ".tree");

	/*  Evaluation  */
	strTemp0.Format(_T("%d"),MaxItem+1);
	vecstrOutput.push_back(_T("\n\nEvaluation on training data (")+strTemp0+_T(" items):\n"));
	Evaluate(false, Best);

	if ( UNSEENS )
	{   
		GetData(".test");
		strTemp0.Format(_T("%d"),MaxItem+1);

		vecstrOutput.push_back(_T("\nEvaluation on test data (")+strTemp0+_T(" items):\n"));
		Evaluate(true, Best);
	}
	delete filename;
	return vecstrOutput;
	vecstrOutput.resize(0);
}
